#pragma once

/*
 * kcp net interface
 */
#include <stddef.h>

#if defined(WIN32) || defined(WIN64)
    #ifndef GNAPI
      #define GNAPI _stdcall
    #endif
#else
    #define GNAPI
#endif

// please replace it to the log function.
#define ADebug printf

namespace KCP {
	// kcp connection interface.
	class IKConnection {
	public:
		virtual ~IKConnection() {}

		// get conversation id.
		virtual unsigned int GNAPI GetConv() = 0;

		// disconnect, just be strictly to use this function.
		virtual void GNAPI Disconnect() = 0;

		// send kcp message.
		virtual void GNAPI SendMsg(const char *msg, int len) = 0;
	};
    
	// kcp session, which is implemented by user.
	class IKSession {
	public:
		virtual ~IKSession() {}

		// set connection handle.
		virtual void GNAPI setConnection(IKConnection *conn) = 0;

		// recv data callback.
		// disconnect return false, else true.
		virtual bool GNAPI onRecv(const char *data, int len) = 0;

		// connection close callback
		virtual void GNAPI onClose() = 0;

		// connection establish callback
		virtual void GNAPI onEstablish() = 0;

		// release session.
		virtual void GNAPI release() = 0;
	};

	// session factory, which is implemented by user.
	// this class can create session.
	class IKSessionFactory {
	public:
		virtual ~IKSessionFactory() {}
		
		// create session and return IKSession*
		virtual IKSession* GNAPI CreateSession() = 0;
	};

	// kcp server interface: for a (ip,port) manager.
	class IKServer {
	public:
		virtual ~IKServer() {}

		// Stop me
		virtual void GNAPI Stop() = 0;

		// all connection size.
		virtual size_t GNAPI GetConnectionSize() = 0;
	};

	// kcp module
	class IKcpModule {
	public:
		virtual ~IKcpModule() {}

		// Init
		virtual bool GNAPI Init() = 0;

		// Run, bool true is busy, else not.
		virtual bool GNAPI Run(int count) = 0;

		// Server Listen
		virtual IKServer* GNAPI Listen(const char *ip, unsigned short port, IKSessionFactory *factory) = 0;
		
		// Client Connect
		virtual bool GNAPI Connect(const char *ip, unsigned short port, IKSessionFactory *factory) = 0;
	};

	// Get Kcp Module.
	IKcpModule* GNAPI GetKcpModule();
}